/*
 *
 *                  Copyright 2017 Crab2Died
 *                     All rights reserved.
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Browse for more information ：
 * 1) https://gitee.com/Crab2Died/Excel4J
 * 2) https://github.com/Crab2died/Excel4J
 *
 */

package com.github.crab2died;

import com.github.crab2died.converter.DefaultConvertible;
import com.github.crab2died.converter.WriteConvertible;
import com.github.crab2died.exceptions.Excel4jReadException;
import com.github.crab2died.handler.ExcelHeader;
import com.github.crab2died.handler.ExcelTemplate;
import com.github.crab2died.utils.Utils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Excel4J的主要操作工具类
 * <p>
 * 主要包含6大操作类型,并且每个类型都配有一个私有handler：<br>
 * 1.读取Excel操作基于注解映射,handler为{@link ExcelUtils#readExcel2ObjectsHandler}<br>
 * 2.读取Excel操作无映射,handler为{@link ExcelUtils#readExcel2ObjectsHandler}<br>
 * 3.基于模板、注解导出excel,handler为{@link ExcelUtils#exportExcelByModuleHandler}<br>
 * 4.基于模板、注解导出Map数据,handler为{@link ExcelUtils#exportExcelByModuleHandler}<br>
 * 5.无模板基于注解导出,handler为{@link ExcelUtils#exportExcelNoModuleHandler}<br>
 * 6.无模板无注解导出,handler为{@link ExcelUtils#exportExcelNoModuleHandler}<br>
 * <p>
 * 另外列举了部分常用的参数格式的方法(不同参数的排列组合实在是太多,没必要完全列出) 如遇没有自己需要的参数类型的方法,可通过最全的方法来自行变换<br>
 * <p>
 * 详细用法请关注: https://gitee.com/Crab2Died/Excel4J
 *
 * @author Crab2Died
 */
public class ExcelUtils {

	/**
	 * 单例模式
	 * <p>
	 * 通过{@link ExcelUtils#getInstance()}获取对象实例
	 */
	static private ExcelUtils excelUtils = new ExcelUtils();

	private ExcelUtils() {
	}

	public static ExcelUtils getInstance() {
		return excelUtils;
	}

	/*---------------------------------------1.读取Excel操作基于注解映射--------------------------------------------*/
	/* 一. 操作流程 ： */
	/* 1) 读取表头信息,与给出的Class类注解匹配 */
	/* 2) 读取表头下面的数据内容, 按行读取, 并映射至java对象 */
	/* 二. 参数说明 */
	/* *) excelPath => 目标Excel路径 */
	/* *) InputStream => 目标Excel文件流 */
	/* *) clazz => java映射对象 */
	/* *) offsetLine => 开始读取行坐标(默认0) */
	/* *) limitLine => 最大读取行数(默认表尾) */
	/* *) sheetIndex => Sheet索引(默认0) */

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param excelPath
	 *            待导出Excel的路径
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param limitLine
	 *            最大读取行数(默认表尾)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(String excelPath, Class<T> clazz, int offsetLine, int limitLine,
			int sheetIndex) throws Exception {
		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2ObjectsHandler(workbook, clazz, offsetLine, limitLine, sheetIndex);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param excelPath
	 *            待导出Excel的路径
	 * @param Map
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param limitLine
	 *            最大读取行数(默认表尾)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public  List<Map<String,Object>> readExcel2Maps(String excelPath,int headerIndex, int offsetLine, int limitLine, int sheetIndex,Map<String,Class<?>> types)
			throws Exception {
		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2MapsHandler(workbook,headerIndex, offsetLine, limitLine, sheetIndex,types);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param is
	 *            待导出Excel的数据流
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param limitLine
	 *            最大读取行数(默认表尾)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(InputStream is, Class<T> clazz, int offsetLine, int limitLine, int sheetIndex)
			throws Exception {
		Workbook workbook = WorkbookFactory.create(is);
		return readExcel2ObjectsHandler(workbook, clazz, offsetLine, limitLine, sheetIndex);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param excelPath
	 *            待导出Excel的路径
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(String excelPath, Class<T> clazz, int offsetLine, int sheetIndex)
			throws Exception {
		return readExcel2Objects(excelPath, clazz, offsetLine, Integer.MAX_VALUE, sheetIndex);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param excelPath
	 *            待导出Excel的路径
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(String excelPath, Class<T> clazz, int sheetIndex) throws Exception {
		return readExcel2Objects(excelPath, clazz, 0, Integer.MAX_VALUE, sheetIndex);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param excelPath
	 *            待导出Excel的路径
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(String excelPath, Class<T> clazz) throws Exception {
		return readExcel2Objects(excelPath, clazz, 0, Integer.MAX_VALUE, 0);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param is
	 *            待导出Excel的数据流
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(InputStream is, Class<T> clazz, int sheetIndex) throws Exception {
		return readExcel2Objects(is, clazz, 0, Integer.MAX_VALUE, sheetIndex);
	}

	/**
	 * 读取Excel操作基于注解映射成绑定的java对象
	 *
	 * @param is
	 *            待导出Excel的数据流
	 * @param clazz
	 *            待绑定的类(绑定属性注解{@link com.github.crab2died.annotation.ExcelField})
	 * @param <T>
	 *            绑定的数据类
	 * @return 返回转换为设置绑定的java对象集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public <T> List<T> readExcel2Objects(InputStream is, Class<T> clazz) throws Exception {
		return readExcel2Objects(is, clazz, 0, Integer.MAX_VALUE, 0);
	}

	private <T> List<T> readExcel2ObjectsHandler(Workbook workbook, Class<T> clazz, int offsetLine, int limitLine,
			int sheetIndex) throws Exception {

		Sheet sheet = workbook.getSheetAt(sheetIndex);
		Row row = sheet.getRow(offsetLine);
		List<T> list = new ArrayList<>();
		Map<Integer, ExcelHeader> maps = Utils.getHeaderMap(row, clazz);
		if (maps == null || maps.size() <= 0)
			throw new Excel4jReadException(
					"The Excel format to read is not correct, and check to see if the appropriate rows are set");
		long maxLine = sheet.getLastRowNum() > ((long) offsetLine + limitLine) ? ((long) offsetLine + limitLine)
				: sheet.getLastRowNum();

		for (int i = offsetLine + 1; i <= maxLine; i++) {
			row = sheet.getRow(i);
			if (null == row)
				continue;
			T obj = clazz.newInstance();
			for (Cell cell : row) {
				int ci = cell.getColumnIndex();
				ExcelHeader header = maps.get(ci);
				if (null == header)
					continue;
				String val = Utils.getCellValue(cell);
				Object value;
				String filed = header.getFiled();
				// 读取转换器
				if (null != header.getReadConverter()
						&& header.getReadConverter().getClass() != DefaultConvertible.class) {
					value = header.getReadConverter().execRead(val);
				} else {
					// 默认转换
					value = Utils.str2TargetClass(val, header.getFiledClazz());
				}
				Utils.copyProperty(obj, filed, value);
			}
			list.add(obj);
		}
		return list;
	}

	/*---------------------------------------2.读取Excel操作无映射-------------------------------------------------*/
	/* 一. 操作流程 ： */
	/*
	 * *) 按行读取Excel文件,存储形式为 Cell->String => Row->List<Cell> => Excel->List<Row>
	 */
	/* 二. 参数说明 */
	/* *) excelPath => 目标Excel路径 */
	/* *) InputStream => 目标Excel文件流 */
	/* *) offsetLine => 开始读取行坐标(默认0) */
	/* *) limitLine => 最大读取行数(默认表尾) */
	/* *) sheetIndex => Sheet索引(默认0) */

	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param excelPath
	 *            待读取Excel的路径
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param limitLine
	 *            最大读取行数(默认表尾)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(String excelPath, int offsetLine, int limitLine, int sheetIndex)
			throws Exception {

		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2ObjectsHandler(workbook, offsetLine, limitLine, sheetIndex);
	}

	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param is
	 *            待读取Excel的数据流
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @param limitLine
	 *            最大读取行数(默认表尾)
	 * @param sheetIndex
	 *            Sheet索引(默认0)
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(InputStream is, int offsetLine, int limitLine, int sheetIndex)
			throws Exception {

		Workbook workbook = WorkbookFactory.create(is);
		return readExcel2ObjectsHandler(workbook, offsetLine, limitLine, sheetIndex);
	}

	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param excelPath
	 *            待读取Excel的路径
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(String excelPath, int offsetLine) throws Exception {

		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2ObjectsHandler(workbook, offsetLine, Integer.MAX_VALUE, 0);
	}

	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param is
	 *            待读取Excel的数据流
	 * @param offsetLine
	 *            Excel表头行(默认是0)
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(InputStream is, int offsetLine) throws Exception {

		Workbook workbook = WorkbookFactory.create(is);
		return readExcel2ObjectsHandler(workbook, offsetLine, Integer.MAX_VALUE, 0);
	}

	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param excelPath
	 *            待读取Excel的路径
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(String excelPath) throws Exception {

		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2ObjectsHandler(workbook, 0, Integer.MAX_VALUE, 0);
	}
	
	/**
	 * 读取Excel表格数据,返回{@code List[Map[String,Object]]}类型的数据集合
	 *
	 * @param excelPath
	 *            待读取Excel的路径
	 * @return 返回{@code List<Map<String,Object>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author huhu
	 */
	
	public List<Map<String,Object>> readExcel2Map(String excelPath,Map<String, Class<?>> typs) throws Exception{
		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2MapsHandler(workbook,0, 1, Integer.MAX_VALUE, 0,typs);
	}
	
	public List<Map<String,Object>> readExcel2Map(String excelPath) throws Exception{
		Workbook workbook = WorkbookFactory.create(new File(excelPath));
		return readExcel2MapsHandler(workbook,0, 1, Integer.MAX_VALUE, 0,new HashMap<String, Class<?>>());
	}
	
	
	/**
	 * 读取Excel表格数据,返回{@code List[List[String]]}类型的数据集合
	 *
	 * @param is
	 *            待读取Excel的数据流
	 * @return 返回{@code List<List<String>>}类型的数据集合
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public List<List<String>> readExcel2List(InputStream is) throws Exception {

		Workbook workbook = WorkbookFactory.create(is);
		return readExcel2ObjectsHandler(workbook, 0, Integer.MAX_VALUE, 0);
	}

	private List<List<String>> readExcel2ObjectsHandler(Workbook workbook, int offsetLine, int limitLine,
			int sheetIndex) throws Exception {

		List<List<String>> list = new ArrayList<>();
		Sheet sheet = workbook.getSheetAt(sheetIndex);
		long maxLine = sheet.getLastRowNum() > ((long) offsetLine + limitLine) ? ((long) offsetLine + limitLine)
				: sheet.getLastRowNum();
		for (int i = offsetLine; i <= maxLine; i++) {
			List<String> rows = new ArrayList<>();
			Row row = sheet.getRow(i);
			if (null == row)
				continue;
			for (Cell cell : row) {
				String val = Utils.getCellValue(cell);
				rows.add(val);
			}
			list.add(rows);
		}
		return list;
	}
	
	private List<Map<String, Object>> readExcel2MapsHandler(Workbook workbook,int headerIndex, int offsetLine, int limitLine,
			int sheetIndex,Map<String,Class<?>> types) throws Exception {

		List<Map<String, Object>> list = new ArrayList<>();
		Sheet sheet = workbook.getSheetAt(sheetIndex);
		long maxLine = sheet.getLastRowNum() > ((long) offsetLine + limitLine) ? ((long) offsetLine + limitLine)
				: sheet.getLastRowNum();
		Map<Integer,String> header=new HashMap<>();
		Row hrow = sheet.getRow(headerIndex);
		for (Cell cell : hrow) {
			header.put(cell.getColumnIndex(), Utils.getCellValue(cell));
		}
		
		for (int i = offsetLine; i <= maxLine; i++) {
			Map<String,Object> temp=new HashMap<>();
			Row row = sheet.getRow(i);
			if (null == row)
				continue;
			for (Cell cell : row) {
				String val = Utils.getCellValue(cell);
				Class<?> clazz =types.get(header.get(cell.getColumnIndex()));
				if(clazz ==null){
					clazz = String.class;
				}
				Object value= Utils.str2TargetClass(val, clazz);
				
				temp.put(header.get(cell.getColumnIndex()), value);
			}
			list.add(temp);
		}
		return list;
	}

	/*-------------------------------------------3.基于模板、注解导出excel------------------------------------------*/
	/* 一. 操作流程 ： */
	/* 1) 初始化模板 */
	/* 2) 根据Java对象映射表头 */
	/* 3) 写入数据内容 */
	/* 二. 参数说明 */
	/* *) templatePath => 模板路径 */
	/* *) sheetIndex => Sheet索引(默认0) */
	/* *) data => 导出内容List集合 */
	/* *) extendMap => 扩展内容Map(具体就是key匹配替换模板#key内容) */
	/* *) clazz => 映射对象Class */
	/* *) isWriteHeader => 是否写入表头 */
	/* *) targetPath => 导出文件路径 */
	/* *) os => 导出文件流 */

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param sheetIndex
	 *            指定导出Excel的sheet索引号(默认为0)
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写表头
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, int sheetIndex, List<?> data, Map<String, String> extendMap,
			Class clazz, boolean isWriteHeader, String targetPath) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, extendMap, clazz, isWriteHeader)
				.write2File(targetPath);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param sheetIndex
	 *            指定导出Excel的sheet索引号(默认为0)
	 * @param data
	 *            待导出数据的集合
	 * @param header
	 * 			  导出选择头部  key 数据key ，value (排序:表头名)如(1:用户名)
	 * @param covers 转换器 key 数据key value 对应转换器
	 * 
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写表头
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportMaps2Excel(String templatePath, int sheetIndex, List<Map<String,Object>> data,Map<String,String> header,Map<String,WriteConvertible> covers, Map<String, String> extendMap,
			boolean isWriteHeader, String targetPath) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, header,covers,extendMap,  isWriteHeader)
				.write2File(targetPath);
	}
	public void exportMaps2Excel(String templatePath, int sheetIndex, List<Map<String,Object>> data,Map<String,String> header,Map<String,WriteConvertible> covers, Map<String, String> extendMap,
			boolean isWriteHeader, OutputStream os) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, header,covers,extendMap,  isWriteHeader)
				.write2Stream(os);
	}
	
	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param sheetIndex
	 *            指定导出Excel的sheet索引号(默认为0)
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写表头
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, int sheetIndex, List<?> data, Map<String, String> extendMap,
			Class clazz, boolean isWriteHeader, OutputStream os) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, extendMap, clazz, isWriteHeader).write2Stream(os);
	}

	public void exportMas2Excel(String templatePath, int sheetIndex, List<Map<String,Object>> data,Map<String, String> header,Map<String, WriteConvertible> convert ,Map<String, String> extendMap,
			 boolean isWriteHeader, OutputStream os) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data,header,convert, extendMap,  isWriteHeader).write2Stream(os);
	}
	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写表头
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Map<String, String> extendMap, Class clazz,
			boolean isWriteHeader, String targetPath) throws Exception {

		exportObjects2Excel(templatePath, 0, data, extendMap, clazz, isWriteHeader, targetPath);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写表头
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Map<String, String> extendMap, Class clazz,
			boolean isWriteHeader, OutputStream os) throws Exception {

		exportObjects2Excel(templatePath, 0, data, extendMap, clazz, isWriteHeader, os);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Map<String, String> extendMap, Class clazz,
			String targetPath) throws Exception {

		exportObjects2Excel(templatePath, 0, data, extendMap, clazz, true, targetPath);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Map<String, String> extendMap, Class clazz,
			OutputStream os) throws Exception {

		exportObjects2Excel(templatePath, 0, data, extendMap, clazz, true, os);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param clazz
	 *            映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Class clazz, String targetPath)
			throws Exception {

		exportObjects2Excel(templatePath, 0, data, null, clazz, true, targetPath);
	}

	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data 
	 *            待导出数据的集合
	 * @param headr 导出头及其排序  key 为数据key  value为 序号:头显示
	 *            映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportMaps2Excel(String templatePath, List<Map<String,Object>> data, Map<String,String> header, String targetPath)
			throws Exception {
		exportMaps2Excel(templatePath, 0, data,header,new HashMap<String,WriteConvertible>(), null, true, targetPath);
	}
	
	
	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param clazz
	 *            映射对象Class
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(String templatePath, List<?> data, Class clazz, OutputStream os) throws Exception {

		exportObjects2Excel(templatePath, 0, data, null, clazz, true, os);
	}

	
	/**
	 * 基于Excel模板与注解{@link com.github.crab2died.annotation.ExcelField}导出Excel
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出数据的集合
	 * @param header
	 *            映射对象导出头部定义
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportMaps2Excel(String templatePath, List<Map<String,Object>> data, Map<String, String> header, OutputStream os) throws Exception {

		exportMaps2Excel(templatePath, 0, data,header,new HashMap<String, WriteConvertible>(), null,  true, os);
	}
	
	private ExcelTemplate exportExcelByModuleHandler(String templatePath, int sheetIndex, List<?> data,
			Map<String, String> extendMap, Class clazz, boolean isWriteHeader) throws Exception {

		if (sheetIndex < 0)
			sheetIndex = 0;
		ExcelTemplate templates = ExcelTemplate.getInstance(templatePath, sheetIndex);
		templates.extendData(extendMap);
		List<ExcelHeader> headers = Utils.getHeaderList(clazz);
		if (isWriteHeader) {
			// 写标题
			templates.createNewRow();
			for (ExcelHeader header : headers) {
				templates.createCell(header.getTitle(), null);
			}
		}

		for (Object object : data) {
			templates.createNewRow();
			templates.insertSerial(null);
			for (ExcelHeader header : headers) {
				templates.createCell(Utils.getProperty(object, header.getFiled(), header.getWriteConverter()), null);
			}
		}
		return templates;
	}

	
	private ExcelTemplate exportExcelByModuleHandler(String templatePath, int sheetIndex, List<Map<String,Object>> data,Map<String,String> header,
			Map<String, WriteConvertible> writeConvertibles,Map<String, String> extendMap,  boolean isWriteHeader) throws Exception {

		if (sheetIndex < 0)
			sheetIndex = 0;
		ExcelTemplate templates = ExcelTemplate.getInstance(templatePath, sheetIndex);
		templates.extendData(extendMap);
		List<ExcelHeader> headers = Utils.getHeaderList(header);
		if (isWriteHeader) {
			// 写标题
			templates.createNewRow();
			for (ExcelHeader theader : headers) {
				templates.createCell(theader.getTitle(), null);
			}
		}

		for (Map<String,Object> object : data) {
			templates.createNewRow();
			templates.insertSerial(null);
			for (ExcelHeader theader : headers) {
				templates.createCell(Utils.getMapProperty(object, theader.getFiled(), writeConvertibles.get(theader.getFiled())!=null?writeConvertibles.get(theader.getFiled()):theader.getWriteConverter()), null);
			}
		}
		return templates;
	}
	
	/*-------------------------------------4.基于模板、注解导出Map数据----------------------------------------------*/
	/* 一. 操作流程 ： */
	/* 1) 初始化模板 */
	/* 2) 根据Java对象映射表头 */
	/* 3) 写入数据内容 */
	/* 二. 参数说明 */
	/* *) templatePath => 模板路径 */
	/* *) sheetIndex => Sheet索引(默认0) */
	/* *) data => 导出内容Map集合 */
	/* *) extendMap => 扩展内容Map(具体就是key匹配替换模板#key内容) */
	/* *) clazz => 映射对象Class */
	/* *) isWriteHeader => 是否写入表头 */
	/* *) targetPath => 导出文件路径 */
	/* *) os => 导出文件流 */

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param sheetIndex
	 *            指定导出Excel的sheet索引号(默认为0)
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, int sheetIndex, Map<String, List<?>> data,
			Map<String, String> extendMap, Class clazz, boolean isWriteHeader, String targetPath) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, extendMap, clazz, isWriteHeader)
				.write2File(targetPath);
	}

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param sheetIndex
	 *            指定导出Excel的sheet索引号(默认为0)
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, int sheetIndex, Map<String, List<?>> data,
			Map<String, String> extendMap, Class clazz, boolean isWriteHeader, OutputStream os) throws Exception {

		exportExcelByModuleHandler(templatePath, sheetIndex, data, extendMap, clazz, isWriteHeader).write2Stream(os);
	}

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, Map<String, List<?>> data, Map<String, String> extendMap,
			Class clazz, String targetPath) throws Exception {

		exportExcelByModuleHandler(templatePath, 0, data, extendMap, clazz, true).write2File(targetPath);
	}

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param extendMap
	 *            扩展内容Map数据(具体就是key匹配替换模板#key内容,详情请查阅Excel模板定制方法)
	 * @param clazz
	 *            映射对象Class
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, Map<String, List<?>> data, Map<String, String> extendMap,
			Class clazz, OutputStream os) throws Exception {

		exportExcelByModuleHandler(templatePath, 0, data, extendMap, clazz, true).write2Stream(os);
	}

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param clazz
	 *            映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, Map<String, List<?>> data, Class clazz, String targetPath)
			throws Exception {

		exportExcelByModuleHandler(templatePath, 0, data, null, clazz, true).write2File(targetPath);
	}

	/**
	 * 基于模板、注解导出{@code Map[String, List[?]]}类型数据 模板定制详见定制说明
	 *
	 * @param templatePath
	 *            Excel模板路径
	 * @param data
	 *            待导出的{@code Map<String, List<?>>}类型数据
	 * @param clazz
	 *            映射对象Class
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObject2Excel(String templatePath, Map<String, List<?>> data, Class clazz, OutputStream os)
			throws Exception {

		exportExcelByModuleHandler(templatePath, 0, data, null, clazz, true).write2Stream(os);
	}

	private ExcelTemplate exportExcelByModuleHandler(String templatePath, int sheetIndex, Map<String, List<?>> data,
			Map<String, String> extendMap, Class clazz, boolean isWriteHeader) throws Exception {

		if (sheetIndex < 0)
			sheetIndex = 0;
		ExcelTemplate templates = ExcelTemplate.getInstance(templatePath, sheetIndex);
		templates.extendData(extendMap);
		List<ExcelHeader> headers = Utils.getHeaderList(clazz);
		if (isWriteHeader) {
			// 写标题
			templates.createNewRow();
			for (ExcelHeader header : headers) {
				templates.createCell(header.getTitle(), null);
			}
		}
		for (Map.Entry<String, List<?>> entry : data.entrySet()) {
			for (Object object : entry.getValue()) {
				templates.createNewRow();
				templates.insertSerial(entry.getKey());
				for (ExcelHeader header : headers) {
					templates.createCell(Utils.getProperty(object, header.getFiled(), header.getWriteConverter()),
							entry.getKey());
				}
			}
		}

		return templates;
	}

	/*--------------------------------------5.无模板基于注解导出---------------------------------------------------*/
	/* 一. 操作流程 ： */
	/* 1) 根据Java对象映射表头 */
	/* 2) 写入数据内容 */
	/* 二. 参数说明 */
	/* *) data => 导出内容List集合 */
	/* *) isWriteHeader => 是否写入表头 */
	/* *) sheetName => Sheet索引名(默认0) */
	/* *) clazz => 映射对象Class */
	/* *) isXSSF => 是否Excel2007及以上版本 */
	/* *) targetPath => 导出文件路径 */
	/* *) os => 导出文件流 */

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param sheetName
	 *            指定导出Excel的sheet名称
	 * @param isXSSF
	 *            导出的Excel是否为Excel2007及以上版本(默认是)
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, boolean isWriteHeader, String sheetName, boolean isXSSF,
			String targetPath) throws Exception {

		FileOutputStream fos = new FileOutputStream(targetPath);
		exportExcelNoModuleHandler(data, clazz, isWriteHeader, sheetName, isXSSF).write(fos);
	}

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param sheetName
	 *            指定导出Excel的sheet名称
	 * @param isXSSF
	 *            导出的Excel是否为Excel2007及以上版本(默认是)
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, boolean isWriteHeader, String sheetName, boolean isXSSF,
			OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, clazz, isWriteHeader, sheetName, isXSSF).write(os);
	}

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, boolean isWriteHeader, String targetPath)
			throws Exception {

		FileOutputStream fos = new FileOutputStream(targetPath);
		exportExcelNoModuleHandler(data, clazz, isWriteHeader, null, true).write(fos);
	}

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param isWriteHeader
	 *            是否写入表头
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, boolean isWriteHeader, OutputStream os)
			throws Exception {

		exportExcelNoModuleHandler(data, clazz, isWriteHeader, null, true).write(os);
	}

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, OutputStream os) throws Exception {
		exportExcelNoModuleHandler(data, clazz, true, null, true).write(os);
	}

	/**
	 * 无模板、基于注解的数据导出
	 *
	 * @param data
	 *            待导出数据
	 * @param clazz
	 *            {@link com.github.crab2died.annotation.ExcelField}映射对象Class
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, Class clazz, String targetPath) throws Exception {

		FileOutputStream fos = new FileOutputStream(targetPath);
		exportExcelNoModuleHandler(data, clazz, true, null, true).write(fos);
	}

	private Workbook exportExcelNoModuleHandler(List<?> data, Class clazz, boolean isWriteHeader, String sheetName,
			boolean isXSSF) throws Exception {

		Workbook workbook;
		if (isXSSF) {
			workbook = new XSSFWorkbook();
		} else {
			workbook = new HSSFWorkbook();
		}
		Sheet sheet;
		if (null != sheetName && !"".equals(sheetName)) {
			sheet = workbook.createSheet(sheetName);
		} else {
			sheet = workbook.createSheet();
		}
		Row row = sheet.createRow(0);
		List<ExcelHeader> headers = Utils.getHeaderList(clazz);
		if (isWriteHeader) {
			// 写标题
			for (int i = 0; i < headers.size(); i++) {
				row.createCell(i).setCellValue(headers.get(i).getTitle());
			}
		}
		// 写数据
		Object _data;
		for (int i = 0; i < data.size(); i++) {
			row = sheet.createRow(i + 1);
			_data = data.get(i);
			for (int j = 0; j < headers.size(); j++) {
				row.createCell(j).setCellValue(
						Utils.getProperty(_data, headers.get(j).getFiled(), headers.get(j).getWriteConverter()));
			}
		}
		return workbook;
	}
	private Workbook exportExcelNoModuleHandler(List<Map<String, Object>> data, Map<String, String> header,Map<String, WriteConvertible> cover, boolean isWriteHeader, String sheetName,
			boolean isXSSF) throws Exception {

		Workbook workbook;
		if (isXSSF) {
			workbook = new XSSFWorkbook();
		} else {
			workbook = new HSSFWorkbook();
		}
		Sheet sheet;
		if (null != sheetName && !"".equals(sheetName)) {
			sheet = workbook.createSheet(sheetName);
		} else {
			sheet = workbook.createSheet();
		}
		Row row = sheet.createRow(0);
		List<ExcelHeader> headers = Utils.getHeaderList(header);
		if (isWriteHeader) {
			// 写标题
			for (int i = 0; i < headers.size(); i++) {
				row.createCell(i).setCellValue(headers.get(i).getTitle());
			}
		}
		// 写数据
		Map<String, Object> _data;
		
				
		for (int i = 0; i < data.size(); i++) {
			row = sheet.createRow(i + 1);
			_data = data.get(i);
			for (int j = 0; j < headers.size(); j++) {
				row.createCell(j).setCellValue(
						Utils.getMapProperty(_data, headers.get(j).getFiled(), cover.get(headers.get(j).getFiled()) !=null?cover.get(headers.get(j).getFiled()):headers.get(j).getWriteConverter()));
			}
		}
		return workbook;
	}
	/*---------------------------------------6.无模板无注解导出----------------------------------------------------*/
	/* 一. 操作流程 ： */
	/* 1) 写入表头内容(可选) */
	/* 2) 写入数据内容 */
	/* 二. 参数说明 */
	/* *) data => 导出内容List集合 */
	/* *) header => 表头集合,有则写,无则不写 */
	/* *) sheetName => Sheet索引名(默认0) */
	/* *) isXSSF => 是否Excel2007及以上版本 */
	/* *) targetPath => 导出文件路径 */
	/* *) os => 导出文件流 */

	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param header
	 *            设置表头信息
	 * @param sheetName
	 *            指定导出Excel的sheet名称
	 * @param isXSSF
	 *            导出的Excel是否为Excel2007及以上版本(默认是)
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, List<String> header, String sheetName, boolean isXSSF,
			String targetPath) throws Exception {

		exportExcelNoModuleHandler(data, header, sheetName, isXSSF).write(new FileOutputStream(targetPath));
	}

	public void exportMaps2Excel(List<Map<String, Object>> data, Map<String,String> header,Map<String, WriteConvertible> cover,boolean isWriteHeader, String sheetName, boolean isXSSF,
			String targetPath) throws Exception {

		exportExcelNoModuleHandler(data, header,cover, isWriteHeader,sheetName, isXSSF).write(new FileOutputStream(targetPath));
	}
	
	public void exportMaps2Excel(List<Map<String, Object>> data, Map<String,String> header,Map<String, WriteConvertible> cover,boolean isWriteHeader, String sheetName, boolean isXSSF,
			OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, header,cover, isWriteHeader,sheetName, isXSSF).write(os);
	}
	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param header
	 *            设置表头信息
	 * @param sheetName
	 *            指定导出Excel的sheet名称
	 * @param isXSSF
	 *            导出的Excel是否为Excel2007及以上版本(默认是)
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, List<String> header, String sheetName, boolean isXSSF,
			OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, header, sheetName, isXSSF).write(os);
	}

	public void exportMaps2Excel(List<Map<String, Object>> data, Map<String,String> header,Map<String,WriteConvertible> cover,  String sheetName, boolean isXSSF,
			OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, header, cover,true,sheetName, isXSSF).write(os);
	}
	
	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param header
	 *            设置表头信息
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, List<String> header, String targetPath) throws Exception {

		exportExcelNoModuleHandler(data, header, null, true).write(new FileOutputStream(targetPath));
	}

	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param header
	 *            设置表头信息
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, List<String> header, OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, header, null, true).write(os);
	}

	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param targetPath
	 *            生成的Excel输出全路径
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, String targetPath) throws Exception {

		exportExcelNoModuleHandler(data, null, null, true).write(new FileOutputStream(targetPath));
	}

	/**
	 * 无模板、无注解的数据(形如{@code List[?]}、{@code List[List[?]]}、{@code List[Object[]]})导出
	 *
	 * @param data
	 *            待导出数据
	 * @param os
	 *            生成的Excel待输出数据流
	 * @throws Exception
	 *             异常
	 * @author Crab2Died
	 */
	public void exportObjects2Excel(List<?> data, OutputStream os) throws Exception {

		exportExcelNoModuleHandler(data, null, null, true).write(os);
	}

	private Workbook exportExcelNoModuleHandler(List<?> data, List<String> header, String sheetName, boolean isXSSF)
			throws Exception {

		Workbook workbook;
		if (isXSSF) {
			workbook = new XSSFWorkbook();
		} else {
			workbook = new HSSFWorkbook();
		}
		Sheet sheet;
		if (null != sheetName && !"".equals(sheetName)) {
			sheet = workbook.createSheet(sheetName);
		} else {
			sheet = workbook.createSheet();
		}

		int rowIndex = 0;
		if (null != header && header.size() > 0) {
			// 写标题
			Row row = sheet.createRow(rowIndex++);
			for (int i = 0; i < header.size(); i++) {
				row.createCell(i, CellType.STRING).setCellValue(header.get(i));
			}
		}
		for (Object object : data) {
			Row row = sheet.createRow(rowIndex++);
			if (object.getClass().isArray()) {
				for (int j = 0; j < Array.getLength(object); j++) {
					row.createCell(j, CellType.STRING).setCellValue(Array.get(object, j).toString());
				}
			} else if (object instanceof Collection) {
				Collection<?> items = (Collection<?>) object;
				int j = 0;
				for (Object item : items) {
					row.createCell(j++, CellType.STRING).setCellValue(item.toString());
				}
			} else {
				row.createCell(0, CellType.STRING).setCellValue(object.toString());
			}
		}
		return workbook;
	}
	
	public static class ExcelFile implements Comparable<ExcelFile>{
		
		public String sheetName;
		public String fileName;
		public int index;
		public ExcelFile(String sheetName, String fileName, int index) {
			super();
			this.sheetName = sheetName;
			this.fileName = fileName;
			this.index = index;
		}
		
		@Override
		public int compareTo(ExcelFile o) {
			// TODO Auto-generated method stub
			return index-o.index;
		}
		
	}
	
	/*public void mergeExcelFileS(String fileName,Map<String,String> files, boolean isXSSF){
		
		Workbook workbook;
		if (isXSSF) {
			workbook = new XSSFWorkbook();
		} else {
			workbook = new HSSFWorkbook();
		}
		//初始化导出
		List<ExcelFile> mergefiles=new ArrayList<>();		
		for (Entry<String, String> entry : files.entrySet()) {			
			String[] key=entry.getKey().split(":");			
			ExcelFile temp =new ExcelFile(key[1], entry.getValue(), Integer.parseInt(key[0]));
		}
		Collections.sort(mergefiles);
		
		for (ExcelFile excelFile : mergefiles) {
			Sheet sheet=workbook.createSheet(excelFile.sheetName);
			sheet。
		}
		
		
		if (null != sheetName && !"".equals(sheetName)) {
			sheet = workbook.createSheet(sheetName);
		} else {
			sheet = workbook.createSheet();
		}

		int rowIndex = 0;
		if (null != header && header.size() > 0) {
			// 写标题
			Row row = sheet.createRow(rowIndex++);
			for (int i = 0; i < header.size(); i++) {
				row.createCell(i, CellType.STRING).setCellValue(header.get(i));
			}
		}
		for (Object object : data) {
			Row row = sheet.createRow(rowIndex++);
			if (object.getClass().isArray()) {
				for (int j = 0; j < Array.getLength(object); j++) {
					row.createCell(j, CellType.STRING).setCellValue(Array.get(object, j).toString());
				}
			} else if (object instanceof Collection) {
				Collection<?> items = (Collection<?>) object;
				int j = 0;
				for (Object item : items) {
					row.createCell(j++, CellType.STRING).setCellValue(item.toString());
				}
			} else {
				row.createCell(0, CellType.STRING).setCellValue(object.toString());
			}
		}
		return workbook;
	}*/
}
